home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 266_01 / drawlib.c < prev    next >
C/C++ Source or Header  |  1990-07-02  |  10KB  |  337 lines

  1. /*      Front End Plot Utility Routines        File: DRAWLIB.C
  2.         Robert L. Patton, Jr.
  3.         1713 Parkcrest Terrace
  4.         Arlington, TX 76012
  5.            04-30-89
  6. */
  7. #include <math.h>
  8. #include "PLOX.H"
  9. #include "DRAWLIB.H"
  10. #include "MATHLIB.H"
  11. #include "PXLIB.H"
  12. #define  AX Scale->
  13.  
  14. void Annote (X, Y, Offset, Dir, Mode, Side, Word, Font)
  15. /*   ====== */
  16. /*  Draws upright text at a given offset from
  17.     a point on a line in a given direction.   */
  18.  
  19. int  X,Y;     /* coordinates of point, pixels */
  20. int  Offset;  /* distance from line, pixels   */
  21. char Dir;     /* line direction, 'H' or 'V'   */
  22. int  Mode;    /* 0 = text parallel to line centered on point
  23.                  1 = text perpendicular, ended at point     */
  24. int  Side;    /* 1 = clockwise, -1 = ccw      */
  25. char *Word;   /* the text string              */
  26. int  Font;    /* predefined character set number */
  27. {
  28.   int  S, C, Tlen, Xt, Yt, Adjust, Pica;
  29.  
  30.   Pica = TxHigh (Font);
  31.   Tlen = TxWide (strlen (Word), Font);
  32.   S = Isin(Dir);
  33.   C = Icos(Dir);
  34.   Xt = X + Offset * S * Side;
  35.   Yt = Y - Offset * C * Side;
  36.   if (Mode) {
  37.     Adjust = Tlen * (1 - Side);
  38.     Xt += (C*Pica - S*Adjust) / 2;
  39.     Yt -= (S*Pica + C*Adjust) / 2;
  40.   }
  41.   else {
  42.     Xt -= (C*Tlen - S*Pica) / 2;
  43.     Yt -= (S*Tlen + C*Pica) / 2;
  44.   }
  45.   PX_Text (Xt, Yt, Font, 'H', Word);
  46. }
  47.  
  48. void AxNum (Xa, Ya, Dir, Side, Span, Scale, Boxes)
  49. /*   ===== */
  50. /*            Draws a standard numeric axis */
  51. int     Xa,Ya; /* start coordinates, pixels      */
  52. char    Dir;   /* direction, 'H' or 'V'          */
  53. int     Side;  /* side for numbers, 1=CW, -1=CCW */
  54. int     Span;  /* length of axis, pixels         */
  55. SCALING *Scale;/* pointer to scaling values      */
  56. int     Boxes; /* number of divisions            */
  57. {
  58.   double Value;
  59.   char   Digits[30];
  60.   int    Bump, C, Font, Mode, S, X, Y;
  61.   static unsigned Flag=2, Left=0, Right=1;
  62.   #ifdef DEBUG
  63.   printf("AxNum:Xa=%d,Ya=%d,Dir=%c,Side=%d,Span=%d,Boxes=%d\n",
  64.           Xa,Ya,Dir,Side,Span,Boxes);
  65.           ShowScale(Dir,Boxes,Scale);
  66.   #endif
  67.   Font = 1;              /* optional font later */
  68.   S = Isin(Dir);
  69.   C = Icos(Dir);
  70.   Mode = (Dir == 'V');
  71.   PX_Move (Xa, Ya);
  72.   PX_Draw (Xa+Span*C, Ya+Span*S);
  73.   X = Xa;
  74.   Y = Ya;
  75.   for (Value=AX Start; Value<=(AX Start+Boxes*AX DeltaB); Value+=AX DeltaB)
  76.   {
  77.     Bump = (int) ((Value-AX Start)*AX DeltaP+.5);
  78.     X = Xa+C*Bump;
  79.     Y = Ya+S*Bump;
  80.     TicMark (X, Y, 3, Dir, Side);
  81.     Ftoa (Value, Digits);
  82.     Annote (X, Y, 8-3*Mode, Dir, Mode, Side, Digits, Font);
  83.   }
  84. }
  85. /*@@*/
  86. void Bar (X1, Y1, X2, Y2, Dir, Width, Hatch)
  87. /*   ===   Draws a rectangular bar  */
  88.  
  89. int X1,Y1, /* center of one end   */
  90.     X2,Y2, /* center of other end */
  91.     Width, /* width in pixels     */
  92.     Hatch; /* hatching pattern    */
  93. char  Dir; /* direction, H or V   */
  94. {
  95.   int Xa, Ya, Xc, Yc, Xhalf, Yhalf;
  96.  
  97.   Xhalf = (Width * Isin(Dir)) >> 1;
  98.   Yhalf = (Width * Icos(Dir)) >> 1;
  99.   Xa = X1 + Xhalf;
  100.   Ya = Y1 - Yhalf; /* diagonally */
  101.   Xc = X2 - Xhalf; /* opposite   */
  102.   Yc = Y2 + Yhalf; /* corners    */
  103.   if (Hatch!=0) PX_Hatch (Xa,Ya,Xc,Yc);
  104.   PX_Move (Xa,Ya);
  105.   PX_Draw (Xa,Yc);
  106.   PX_Draw (Xc,Yc);
  107.   PX_Draw (Xc,Ya);
  108.   PX_Draw (Xa,Ya);
  109. }
  110.  
  111. void Box (X1,Y1,X2,Y2)
  112. /*   ===              Draw a rectangle */
  113. int X1,Y1,X2,Y2;
  114. {
  115.   PX_Move(X1,Y1);
  116.   PX_Draw(X2,Y1);
  117.   PX_Draw(X2,Y2);
  118.   PX_Draw(X1,Y2);
  119.   PX_Draw(X1,Y1);
  120. }
  121.  
  122. void BoxTry (Span,MinBox,MaxBox)
  123. /*   ======                      Choose the minimum and maximum   */
  124. int Span, *MinBox, *MaxBox;   /* number of scale divisions to try */
  125. {                             /* for any given span in pixels.    */
  126.   if (Span<(1.5*INCH)) {
  127.     *MinBox = 2;
  128.     *MaxBox = 2;
  129.   }
  130.   else {
  131.     *MinBox = Span/INCH;
  132.     if (*MinBox<3) *MinBox = 3;
  133.     *MaxBox = 2*( *MinBox);
  134.   }
  135. }
  136.  
  137. void CopyScale (From, To)
  138. /*   =========       Makes a copy of a SCALING value */
  139. SCALING *From, *To;
  140. {
  141.   To->Start  = From->Start;
  142.   To->DeltaB = From->DeltaB;
  143.   To->DeltaP = From->DeltaP;
  144. }
  145.  
  146. void Fit (Min, Max, Boxes, Start, Delta)
  147. /*   === */
  148. int    Boxes;          /* Finds offset and units/division for   */
  149. double Min,Max;        /* a given range and number of divisions */
  150. double *Start,*Delta;  /* ensuring 1,2,4, or 5 X 10**N per division */
  151. {
  152.   double Divs;
  153.   int  Trial=0;
  154.  
  155.   Divs = (double) Boxes;
  156.   *Delta = 0.5 * Exp10 ((int) floor ((log10 (Max-Min)/Divs)) );
  157.   do
  158.   {
  159.     Trial += 1;
  160.     if (Trial%4 == 3)
  161.          *Delta = 1.25 * *Delta;
  162.     else *Delta = 2.00 * *Delta;
  163.     *Start = *Delta * floor (Min / *Delta);
  164.   }
  165.   while (*Start + Divs * *Delta < Max);
  166. }
  167. /*@@*/
  168. int IsHue (char *Word) {
  169.  /* =====              Returns the color number if Word is a
  170.                        microPLOX color.  Otherwise zero.
  171. */
  172. #define HUES  15
  173. #define HUEBUF 8
  174. char *HueList[HUES] = {"blue  " ,"pea"   ,"aqua"  ,"coral" ,"plum",
  175.                        "umber"  ,"chalk" ,"gray"  ,"azure" ,"lime",
  176.                        "cyan"   ,"peach" ,"lilac" ,"lemon" ,"white"};
  177. int HueNum;
  178.   HueNum = iKeyFind (HueList,HUES,Word);
  179.   return (HueNum<0 ? 0 : HueNum);
  180. }
  181.  
  182. void Liner (Xptr, Xfit, Yptr, Yfit, LineType, PointType)
  183. /*   =====    Draws straight lines between consecutive points in a set
  184.               of X,Y points in arbitrary data units */
  185. float    *Xptr,*Yptr; /* the data points       */
  186. SCALING  *Xfit,*Yfit; /* scaling parameters    */
  187. int      LineType,    /* line pattern, 1=solid */
  188.          PointType;   /* point shape, 0=none   */
  189. {
  190.   int  I, Imax;
  191.  
  192.   PX_Trail (LineType);
  193.   Imax = (int) *Xptr++;
  194.   Yptr++;
  195.   PX_Move (Scaled(Xptr++,Xfit), Scaled(Yptr++,Yfit) );
  196.   if (PointType) PX_Symbol (PointType);
  197.   for (I=1; I<Imax; I++,Xptr++,Yptr++)
  198.   {
  199.     if(LineType) PX_Draw (Scaled(Xptr,Xfit), Scaled(Yptr,Yfit) );
  200.     else         PX_Move (Scaled(Xptr,Xfit), Scaled(Yptr,Yfit) );
  201.     if (PointType) PX_Symbol (PointType);
  202.   }
  203.   PX_Trail (SOLID);
  204. }
  205.  
  206. int Pct_Fit (Min, Max, Boxes)
  207. /*  ======= */
  208. /*             Returns a percent fit of the values generated
  209.                by the standard scaling algorithm */
  210. double Min,Max; /* data extremes */
  211. int    Boxes;   /* number of scale divisions */
  212. {
  213.   double Delta, Start;
  214.  
  215.   Fit (Min, Max, Boxes, &Start, &Delta);
  216.   return ((int) ((Max-Min)*100.0/(Delta*Boxes)+.5));
  217. }
  218.  
  219. void Scale (Min, Max, Span, Exact, Boxes, Adjust)
  220. /*   ===== */
  221. /*             Provides scaling values for a set of data */
  222. double  Min,Max; /* data extremes                        */
  223. int     Span;    /* length of scale, pixels              */
  224. int     Exact;   /* TRUE for ends of scale = Min and Max */
  225. int     *Boxes;  /* number of scale divisions IN OUT     */
  226. SCALING *Adjust; /* the scaling values returned          */
  227. {
  228.   double floor();
  229.   int    BestFit,I,MinBox,MaxBox,ThisFit;
  230.   if (Exact) {
  231.     if (*Boxes) {
  232.       Adjust->Start = Min;
  233.       Adjust->DeltaB = (Max-Min)/(*Boxes);
  234.     }
  235.     else {      /* choose Boxes until 100% fit found */
  236.       BoxTry(Span,&MinBox,&MaxBox);
  237.       for (*Boxes=MinBox; *Boxes<=MaxBox; *Boxes+=1)
  238.         if ((ThisFit=Pct_Fit(Min,Max,*Boxes))==100) break;
  239.       if (*Boxes<=MaxBox)
  240.         Fit(Min,Max,*Boxes,&Adjust->Start,&Adjust->DeltaB);
  241.       else {
  242.         *Boxes = 1;
  243.         Adjust->Start = Min;
  244.         Adjust->DeltaB = Max-Min;
  245.       }
  246.     }
  247.   }
  248.   else {   /* NOT Exact */
  249.     if (*Boxes<=0) {
  250.       BestFit = 0;
  251.       *Boxes = 1;
  252.       BoxTry(Span,&MinBox,&MaxBox);
  253.       for (I=MinBox; I<=MaxBox; I++)
  254.         if ((ThisFit=Pct_Fit(Min,Max,I))>BestFit) {
  255.           *Boxes = I;
  256.           BestFit = ThisFit;
  257.         }
  258.     }
  259.     Fit(Min,Max,*Boxes,&Adjust->Start,&Adjust->DeltaB);
  260.   }
  261.   Adjust->DeltaP = (double) Span/(Adjust->DeltaB*(*Boxes));
  262. }
  263.  
  264. int Scaled (Vptr, Vfit)
  265. /*  ======             Returns the scaled pixel
  266.                        location of a data value */
  267. float   *Vptr; /* data value     */
  268. SCALING *Vfit; /* scaling params */
  269. {
  270.   return ( (int) ((*Vptr - Vfit->Start) * Vfit->DeltaP + .5) );
  271. }
  272.  
  273. void ShowScale (Dir,Boxes,Fit)
  274. /*   =========     Displays scaling values */
  275. char    Dir;